import time
import sys

DF_NORMAL       = 0
DF_INVALID_PAGE = 1
DF_EXTRA_SPACE  = 2
DF_LACK_LEVEL   = 4

def getErrMsg(err_code):
    
    err_msg = []
    if err_code & DF_INVALID_PAGE:
        err_msg.append("非法页数")
    if err_code & DF_EXTRA_SPACE:
        err_msg.append("存在多余空格")
    if err_code & DF_LACK_LEVEL:
        err_msg.append("无法判断级别信息")
    return err_msg

def getErrColor(err_code):
    
    if err_code & DF_INVALID_PAGE:
        return (255,0,0)
    elif err_code & DF_EXTRA_SPACE:
        return (255, 140, 0)
    elif err_code & DF_LACK_LEVEL:
        return (255, 20, 147)
    else:
        return (0, 0, 0)

class DirFormator:
    
    def __init__(self, params = None) -> None:
        
        self.dir_input_path = ''
        self.dir_format_path = ''
        self.dir_log_path = ''
        self.delimiter = ' '
        self.level_marker = '.'
        self.prefix = '\t'
        self.pre_level = 2
        self.pre_title = ''
        
        if params:
            if 'DIR_INPUT_PATH' in params:
                self.dir_input_path = params['DIR_INPUT_PATH'] 
            if 'DIR_FORMAT_PATH' in params:
                self.dir_format_path = params['DIR_FORMAT_PATH']
            if 'DIR_LOG_PATH' in params:
                self.dir_log_path = params['DIR_LOG_PATH']
            if 'DELIMITER' in params:
                self.delimiter = params['DELIMITER']
            if 'LEVEL_MARKER' in params:
                self.level_marker = params['LEVEL_MARKER']
            if 'PREFIX' in params:
                self.prefix = params['PREFIX']
                if self.prefix == "\\t":
                    self.prefix = '\t'
            if 'PRE_LEVEL' in params:
                self.pre_level = int(params['PRE_LEVEL'])
            if 'PRE_TITLE' in params:
                self.pre_title = params['PRE_TITLE'].split(';')
        
    def reset(self, params):
        if params:
            if 'DIR_INPUT_PATH' in params:
                self.dir_input_path = params['DIR_INPUT_PATH'] 
            if 'DIR_FORMAT_PATH' in params:
                self.dir_format_path = params['DIR_FORMAT_PATH']
            if 'DIR_LOG_PATH' in params:
                self.dir_log_path = params['DIR_LOG_PATH']
            if 'DELIMITER' in params:
                self.delimiter = params['DELIMITER']
            if 'LEVEL_MARKER' in params:
                self.level_marker = params['LEVEL_MARKER']
            if 'PREFIX' in params:
                self.prefix = params["PREFIX"]
                if self.prefix == "\\t":
                    self.prefix = '\t'
            if 'PRE_LEVEL' in params:
                self.pre_level = int(params['PRE_LEVEL'])
            if 'PRE_TITLE' in params:
                self.pre_title = params['PRE_TITLE'].split(';')

    def getInfo(self):
        
        tm = time.localtime()
        
        info_str = \
            "运行时间: %04d-%02d-%02d %02d:%02d:%02d\n" \
            "目录源文件路径: %s\n"\
            "格式化目录路径: %s\n"\
            "日志路径: %s\n"\
            "单词分隔符: %s\n"\
            "级别标志符: %s\n"\
            "前缀: %s\n"\
            "预定义级别: %d\n"\
            "预定义标题: %s\n"\
            % (
                tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
                self.dir_input_path,
                self.dir_format_path,
                self.dir_log_path,
                self.delimiter,
                self.level_marker,
                self.prefix,
                self.pre_level,
                ';'.join(self.pre_title)
            )

        return info_str
    
    def run(self, isPrint = False):

        out_lines = []     # 格式化后的每一行字符串
        out_err_codes = [] # 每一行的错误码
        err_line_nums = [] # 格式化目录中出错的行号
        
        if isPrint:
            print("---------------------------- Format Dir -----------------------------------")
            print("%s" % self.getInfo(), end="")
            print("---------------------------------------------------------------------------")
        
        with open(self.dir_input_path, 'r', encoding='utf-8') as fin:
            dot_pos = self.dir_input_path.rfind('.')
            ext_name = self.dir_input_path[dot_pos+1:]
            prefix_str = self.dir_input_path[0:dot_pos]
            
            # 设置输出目录
            if len(self.dir_format_path) == 0:
                self.dir_format_path = prefix_str + "_format." + ext_name
            else:
                output_dot_pos = self.dir_format_path.rfind('.')
                if output_dot_pos != -1:
                    # 存在扩展名 => 给了一个文件路径
                    pass
                else:
                    # 给了一个文件夹目录
                    base_pos = self.dir_input_path.rfind('\\')
                    filename = self.dir_input_path[base_pos+1:]
                    if self.dir_format_path[-1] != '\\':
                        self.dir_format_path = self.dir_format_path + '\\' + filename
                    else:
                        self.dir_format_path = self.dir_format_path + filename
            
            # 设置日志目录
            if len(self.dir_log_path) == 0:
                self.dir_log_path = self.dir_input_path[0:dot_pos] + ".log"
            else:
                log_dot_pos = self.dir_log_path.rfind('.')
                if log_dot_pos != -1:
                    pass
                else:
                    base_pos = self.dir_input_path.rfind('\\')
                    basename = self.dir_input_path[base_pos+1:dot_pos] + ".log"
                    if self.dir_log_path[-1] != '\\':
                        self.dir_log_path = self.dir_log_path + '\\' + basename
                    else:
                        self.dir_log_path = self.dir_log_path + basename
                    
            src_lines = fin.readlines()
            
            line_num = 0
            for sline in src_lines:
                if sline[0] == '\n':
                    continue
                
                # 移除首尾多余的空字符    
                sline = sline.strip()
                
                # 分割字符, 默认是按照空白字符 \t\0 分
                words = sline.split()
                
                # 错误码
                err_code = DF_NORMAL
                
                # 检查页码数
                try:
                    int(words[-1])
                except:
                    err_code = err_code | DF_INVALID_PAGE
                
                # 设置级别
                level = 0
                for ch in words[0]:
                    if ch == self.level_marker:
                        level += 1
                
                # 检查空格数
                if len(words) > 3:
                    err_code = err_code | DF_EXTRA_SPACE
                elif len(words) < 3:
                    if not words[0] in self.pre_title:
                        if level == 0:
                            err_code = err_code | DF_LACK_LEVEL
                    else:
                        # 预定义标题的级别为预定义级别
                        level = self.pre_level - 1
                
                # 格式化该行
                out_line = self.prefix * level + sline + '\n'
                
                out_lines.append(out_line)
                out_err_codes.append(err_code)

                if err_code != DF_NORMAL:
                    err_line_nums.append(line_num)

                line_num = line_num + 1
                
        # 输出格式化目录
        with open(self.dir_format_path, 'w', encoding='utf-8') as fout:
            fout.writelines(out_lines)
        
        # 输出日志
        with open(self.dir_log_path, 'w', encoding='utf-8') as flog:
            flog.write(self.getInfo())
            for err_lid in err_line_nums:
                err_msg = getErrMsg(out_err_codes[err_lid])
                log_str = "[Line %3d] %s ==> %s\n" % (err_lid+1, out_lines[err_lid][:-1], ';'.join(err_msg))
                if isPrint:
                    print(log_str, end="")
                flog.write(log_str) 
            if isPrint:
                print("---------------------------------------------------------------------------")
                print("Dir-log Path    : %s" % self.dir_log_path)
                print("Dir format Path : %s" % self.dir_format_path)
                print("---------------------------------- Done! ----------------------------------")
            
        return out_lines, out_err_codes, err_line_nums
            

if __name__ == '__main__':
    
    # 运行指令
    # python .\dirFormat.py <dir_input_path> [<-option> <params>]

    argc = len(sys.argv)
    params = {'DIR_INPUT_PATH' : sys.argv[1]}
    for i in range(2,argc,2):
        key = sys.argv[i]
        value = sys.argv[i+1]
        if key == '-o':
            key = 'DIR_FORMAT_PATH'
        elif key == '-l':
            key = 'DIR_LOG_PATH'
        elif key == '-d':
            key = 'DELIMITER'
        elif key == '-m':
            key = 'LEVEL_MARKER'
        elif key == '-p':
            key = 'PREFIX'
        elif key == '-pl':
            key = 'PRE_LEVEL'
        elif key == '-pt':
            key = 'PRE_TITLE'
        else:
            continue
        params[key] = value
    
    # params = {
    #     'DIR_INPUT_PATH' : "dir.txt",
    #     'DIR_FORMAT_PATH' : "",
    #     'DIR_LOG_PATH' : "",
    #     'DELIMITER' : ' ',
    #     'LEVEL_MARKER' : '.',
    #     'PREFIX' : '\\t',
    #     'PRE_LEVEL' : '2',
    #     'PRE_TITLE' : "小结;习题"
    # }
    
    dirfmt = DirFormator(params)
    dirfmt.run(True)
    